package com.hethongviet.vending.network;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.hethongviet.vending.Utils;
import com.hethongviet.vending.helper.GeneralActivity;
import com.hethongviet.vending.model.Box;
import com.hethongviet.vending.model.BoxInventory;
import com.hethongviet.vending.model.MachineInfo;
import com.hethongviet.vending.model.ProductSell;
import com.hethongviet.vending.model.ProductService;
import com.hethongviet.vending.network.CONSTANTS.CLIENT_TRANSACTION;
import com.hethongviet.vending.network.CONSTANTS.JSON;
import com.hethongviet.vending.network.CONSTANTS.NETWORK_ERROR;
import com.hethongviet.vending.network.CONSTANTS.SERVICE;

//import java.net.InetSocketAddress;
//import java.nio.charset.Charset;

//import org.apache.mina.core.future.ConnectFuture;
//import org.apache.mina.core.service.IoConnector;
//import org.apache.mina.core.session.IoSession;
//import org.apache.mina.filter.codec.ProtocolCodecFilter;
//import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
//import org.apache.mina.filter.logging.LoggingFilter;
//import org.apache.mina.transport.socket.nio.NioSocketConnector;

public class NetworkMina
{
	private static String _host = SERVICE.SERVER_URL;
	private static int _port = CONFIG.NETWORK_PORT;

	private static GeneralActivity onNetworkHandleListener = null;

	public static void send(final String messageOut)
	{
		new Thread(new Runnable() {

			@Override
			public void run()
			{
				try
				{
					// System.out.println("Open connect...");
					// IoConnector connector = new NioSocketConnector();
					// connector.getSessionConfig().setReadBufferSize(2048);
					//
					// System.out.println("Add Logging Filter..");
					// connector.getFilterChain().addLast("logger", new
					// LoggingFilter());
					//
					// System.out.println("Add Protocol Codec Filter..");
					// connector.getFilterChain().addLast(
					// "codec",
					// new ProtocolCodecFilter(new TextLineCodecFactory(
					// Charset.forName("UTF-8"))));
					//
					// System.out.println("Add handler..");
					// connector.setHandler(new MinaClientHandler(messageOut));
					//
					// System.out.println("Connecting to " + host + " via port "
					// +
					// port);
					// ConnectFuture future = connector.connect(new
					// InetSocketAddress(host,
					// port));
					//
					// System.out.println("Wait to interrupt..");
					// future.awaitUninterruptibly();
					//
					// if (!future.isConnected())
					// {
					// return;
					// }
					//
					// System.out.println("Get session..");
					// IoSession session = future.getSession();
					// session.getConfig().setUseReadOperation(true);
					// session.getCloseFuture().awaitUninterruptibly();
					//
					// System.out.println("Close!");
					// connector.dispose();

					Socket kkSocket = null;
					PrintWriter out = null;
					BufferedReader in = null;
					System.out.println("Connecting to " + _host + " via port "
							+ _port);
					try
					{
						kkSocket = new Socket(_host, _port);
						out = new PrintWriter(kkSocket.getOutputStream(), true);
						in = new BufferedReader(new InputStreamReader(
								kkSocket.getInputStream()));
					} catch (UnknownHostException e)
					{
						e.printStackTrace();
						System.err.println("Don't know about host: " + _host);
						// System.exit(1);
						getOnNetworkHandleListener().onConnectFail(NETWORK_ERROR.HOST);
						return;
					} catch (IOException e)
					{
						e.printStackTrace();
						System.err.println("Couldn't get I/O for the connection to: "
								+ _host);
						getOnNetworkHandleListener().onConnectFail(NETWORK_ERROR.IO);
						// System.exit(1);
						return;
					}

					// if (messageOut != null)
					// {
					// System.out.println("Client: " + messageOut);
					// out.println(messageOut);
					// }
					//
					// // BufferedReader stdIn = new BufferedReader(new
					// // InputStreamReader(System.in));
					// String fromServer;
					// StringBuffer response = new StringBuffer();
					// //
					// // while ((fromServer = in.readLine()) != null)
					// // {
					// // response.append(fromServer);
					// // }
					//
					// //
					// // Read and display the response message sent by server
					// application
					// //
					// ObjectInputStream ois = new
					// ObjectInputStream(kkSocket.getInputStream());
					// String message = (String) ois.readObject();
					// System.out.println("Message out : " + message);
					//
					//

					BufferedReader stdIn = new BufferedReader(
							new InputStreamReader(System.in));
					String fromServer;
					String fromUser;

					out.println(messageOut);

					while ((fromServer = in.readLine()) != null)
					{
						System.out.println("Server: " + fromServer);
						if (getOnNetworkHandleListener() != null) getOnNetworkHandleListener().onNetworkMessageIncomming(null);
						// if (fromServer.equals("Bye.")) break;

						fromUser = stdIn.readLine();
						if (fromUser != null)
						{
							System.out.println("Client: " + fromUser);
							out.println(fromUser);
						}
					}

					// String messageIn = response.toString();
					// System.out.println("Server: " + messageIn);
					// if (onNetworkSuccessListener != null)
					// onNetworkSuccessListener.onMessageIncomming(messageIn);

					out.close();
					in.close();
					// ois.close();
					stdIn.close();
					kkSocket.close();

				} catch (Exception e)
				{
					e.printStackTrace();
					// onNetworkFailListener.onConnectFail(NETWORK_ERROR.CONNECT);
				}
			}
		}).start();

	}

	public static boolean sendProductSell(ProductSell productSell,
			MachineInfo machineInfo)
	{
		/* Create JSON */
		JSONObject jsonObject = new JSONObject();
		try
		{

			// jsonObject.put(CONSTANTS.PRODUCT_SELL.COLUMN_INDEX_MACHINE_ID +
			// "", machineInfo.getMachineId());
			jsonObject.put(CONSTANTS.PRODUCT_SELL.COLUMN_INDEX_ACCOUNT_NUMBER
					+ "", productSell.getAccountNumber());
			jsonObject.put(CONSTANTS.PRODUCT_SELL.COLUMN_INDEX_BOX_CODE + "",
					productSell.getIdBox());
			jsonObject.put(CONSTANTS.PRODUCT_SELL.COLUMN_INDEX_PRODUCT_CODE
					+ "", productSell.getCodeProduct());
			jsonObject.put(CONSTANTS.PRODUCT_SELL.COLUMN_INDEX_DATE + "",
					productSell.getDate());
			jsonObject.put(CONSTANTS.PRODUCT_SELL.COLUMN_INDEX_IS_DELIVERIED
					+ "", productSell.isDelivered());
			jsonObject.put(CONSTANTS.PRODUCT_SELL.COLUMN_INDEX_PRICE + "",
					productSell.getPrice());

		} catch (JSONException e)
		{
			e.printStackTrace();
			return false;
		}

		JSONObject jsonObject2 = new JSONObject();
		try
		{
			jsonObject2.put(CONSTANTS.JSON.KEY_VALUE + "",
					jsonObject.toString());
			jsonObject2.put(CONSTANTS.JSON.KEY_TYPE + "",
					CONSTANTS.CLIENT_TRANSACTION.SELL);

		} catch (JSONException e)
		{
			e.printStackTrace();
			return false;
		}

		/* Send */
		Utils.debug("Sending message = " + jsonObject2.toString());
		NetworkMina.send(jsonObject2.toString());
		return true;
	}

	public static boolean sendMachineInfo(MachineInfo machine)
	{
		/* Create JSON */
		JSONObject jsonObject = new JSONObject();
		try
		{
			jsonObject.put(CONSTANTS.MACHINE.COLUMN_INDEX_AMOUNT_BOX + "",
					machine.getBoxAmount());
			jsonObject.put(CONSTANTS.MACHINE.COLUMN_INDEX_CODE + "",
					machine.getCode());
			jsonObject.put(CONSTANTS.MACHINE.COLUMN_INDEX_DATE_CREATED + "",
					machine.getDateCreated());
			jsonObject.put(CONSTANTS.MACHINE.COLUMN_INDEX_DATE_TERMINATED + "",
					machine.getDateTerminated());
			jsonObject.put(CONSTANTS.MACHINE.COLUMN_INDEX_GROUP + "",
					machine.getGroupId());
			jsonObject.put(CONSTANTS.MACHINE.COLUMN_INDEX_LATITTUDE + "",
					machine.getLatitude());
			jsonObject.put(CONSTANTS.MACHINE.COLUMN_INDEX_LOCATION_ID + "",
					machine.getLocationId());
			jsonObject.put(CONSTANTS.MACHINE.COLUMN_INDEX_LONGITUDE + "",
					machine.getLongitude());
			// jsonObject.put(CONSTANTS.MACHINE.COLUMN_INDEX_STAFF_CREATE + "",
			// machine.getStaffCreate());
			// jsonObject.put(CONSTANTS.MACHINE.COLUMN_INDEX_STAFF_TERMINATE +
			// "",
			// machine.getStaffTerminate());
			// jsonObject.put(CONSTANTS.MACHINE.COLUMN_INDEX_STAFF_UPDATE + "",
			// machine.getStaffUpdate());
			jsonObject.put(CONSTANTS.MACHINE.COLUMN_INDEX_STATUS + "",
					machine.getStatus());
			jsonObject.put(CONSTANTS.MACHINE.COLUMN_INDEX_STATUS_RENT + "",
					machine.getStatusRent());

		} catch (JSONException e)
		{
			e.printStackTrace();
			return false;
		}

		JSONObject jsonObject2 = new JSONObject();
		try
		{
			jsonObject2.put(CONSTANTS.JSON.KEY_VALUE + "",
					jsonObject.toString());
			jsonObject2.put(CONSTANTS.JSON.KEY_TYPE + "",
					CONSTANTS.CLIENT_TRANSACTION.MACHINE);

		} catch (JSONException e)
		{
			e.printStackTrace();
			return false;
		}

		/* Send */
		Utils.debug("Sending message = " + jsonObject2.toString());
		NetworkMina.send(jsonObject2.toString());

		return true;
	}

	public static boolean sendRequestUpdateAccount()
	{

		JSONObject jsonObject = new JSONObject();
		try
		{
			jsonObject.put(CONSTANTS.JSON.KEY_VALUE + "", JSON.NULL);
			jsonObject.put(CONSTANTS.JSON.KEY_TYPE + "",
					CONSTANTS.CLIENT_TRANSACTION.ACCOUNT);

		} catch (JSONException e)
		{
			e.printStackTrace();
			return false;
		}

		/* Send */
		Utils.debug("Sending message = " + jsonObject.toString());
		NetworkMina.send(jsonObject.toString());

		return true;
	}

	public static boolean sendRequestUpdateProduct()
	{

		JSONObject jsonObject = new JSONObject();
		try
		{
			jsonObject.put(CONSTANTS.JSON.KEY_VALUE + "", JSON.NULL);
			jsonObject.put(CONSTANTS.JSON.KEY_TYPE + "",
					CONSTANTS.CLIENT_TRANSACTION.PRODUCT);

		} catch (JSONException e)
		{
			e.printStackTrace();
			return false;
		}

		/* Send */
		Utils.debug("Sending message = " + jsonObject.toString());
		NetworkMina.send(jsonObject.toString());

		return true;
	}

	public static boolean sendDataToServer(List<ProductSell> productSells,
			List<ProductService> productServices,
			List<BoxInventory> boxInventories, List<Box> boxes)
	{
		JSONObject jsonObjectSend = new JSONObject();
		JSONArray jsonArraySend = new JSONArray();

		/* Process products sale out */
		/* Create JSON */
		JSONArray jsonArraySellOut = new JSONArray();
		try
		{
			for (ProductSell productSell : productSells)
			{
				JSONObject jsonObject = new JSONObject();

				jsonObject.put(
						CONSTANTS.PRODUCT_SELL.COLUMN_INDEX_ACCOUNT_NUMBER + "",
						productSell.getAccountNumber());
				jsonObject.put(CONSTANTS.PRODUCT_SELL.COLUMN_INDEX_AMOUNT + "",
						1);
				jsonObject.put(CONSTANTS.PRODUCT_SELL.COLUMN_INDEX_BOX_CODE
						+ "", productSell.getIdBox());
				jsonObject.put(CONSTANTS.PRODUCT_SELL.COLUMN_INDEX_DATE + "",
						productSell.getDate());
				jsonObject.put(
						CONSTANTS.PRODUCT_SELL.COLUMN_INDEX_IS_DELIVERIED + "",
						productSell.isDelivered());
				jsonObject.put(CONSTANTS.PRODUCT_SELL.COLUMN_INDEX_MACHINE_CODE
						+ "", productSell.getMachineCode());
				jsonObject.put(CONSTANTS.PRODUCT_SELL.COLUMN_INDEX_PRICE + "",
						productSell.getPrice());
				jsonObject.put(CONSTANTS.PRODUCT_SELL.COLUMN_INDEX_PRODUCT_CODE
						+ "", productSell.getCodeProduct());
				jsonObject.put(CONSTANTS.PRODUCT_SELL.COLUMN_INDEX_WORK_NUMBER1
						+ "", productSell.getWorkerNumber1());
				jsonObject.put(CONSTANTS.PRODUCT_SELL.COLUMN_INDEX_WORK_NUMBER2
						+ "", productSell.getWorkerNumber2());

				jsonArraySellOut.put(jsonObject);
			}

			JSONObject jsonObjectElementSellOut = new JSONObject();
			jsonObjectElementSellOut.put(JSON.KEY_TYPE + "",
					CLIENT_TRANSACTION.SELL);
			jsonObjectElementSellOut.put(JSON.KEY_VALUE + "",
					jsonArraySellOut.toString());
			jsonArraySend.put(jsonObjectElementSellOut);

		} catch (JSONException e)
		{
			e.printStackTrace();
			return false;
		}

		/* Process products product put in */
		/* Create JSON */
		JSONArray jsonArrayPutIn = new JSONArray();
		try
		{
			for (ProductService productService : productServices)
			{
				if (productService.getTransaction() == ProductService.TRANSACTION_PRODUCT_PUT_IN)
				{
					JSONObject jsonObject = new JSONObject();

					jsonObject.put(CONSTANTS.PRODUCT_PUT_IN.COLUMN_INDEX_AMOUNT
							+ "", productService.getAmount());
					jsonObject.put(
							CONSTANTS.PRODUCT_PUT_IN.COLUMN_INDEX_BOX_CODE + "",
							productService.getIdBox());
					jsonObject.put(CONSTANTS.PRODUCT_PUT_IN.COLUMN_INDEX_DATE
							+ "", productService.getDate());
					jsonObject.put(
							CONSTANTS.PRODUCT_PUT_IN.COLUMN_INDEX_MACHINE_CODE
									+ "", productService.getMachineCode());
					jsonObject.put(
							CONSTANTS.PRODUCT_PUT_IN.COLUMN_INDEX_PRODUCT_CODE
									+ "", productService.getCodeProduct());
					jsonObject.put(
							CONSTANTS.PRODUCT_PUT_IN.COLUMN_INDEX_STAFF_CHECKER
									+ "", productService.getStaffChecker());
					jsonObject.put(
							CONSTANTS.PRODUCT_PUT_IN.COLUMN_INDEX_STAFF_SERVICE
									+ "", productService.getStaffService());

					jsonArrayPutIn.put(jsonObject);
				}
			}

			JSONObject jsonObjectElementPutIn = new JSONObject();
			jsonObjectElementPutIn.put(JSON.KEY_TYPE + "",
					CLIENT_TRANSACTION.PRODUCT_PUTIN);
			jsonObjectElementPutIn.put(JSON.KEY_VALUE + "",
					jsonArrayPutIn.toString());
			jsonArraySend.put(jsonObjectElementPutIn);

		} catch (JSONException e)
		{
			e.printStackTrace();
			return false;
		}

		/* Process products take out */
		/* Create JSON */
		JSONArray jsonArrayTakeOut = new JSONArray();
		try
		{
			for (ProductService productService : productServices)
			{

				if (productService.getTransaction() == ProductService.TRANSACTION_PRODUCT_TAKE_OUT)
				{
					JSONObject jsonObject = new JSONObject();

					jsonObject.put(
							CONSTANTS.PRODUCT_TAKE_OUT.COLUMN_INDEX_AMOUNT + "",
							productService.getAmount());
					jsonObject.put(
							CONSTANTS.PRODUCT_TAKE_OUT.COLUMN_INDEX_BOX_CODE
									+ "", productService.getIdBox());
					jsonObject.put(CONSTANTS.PRODUCT_TAKE_OUT.COLUMN_INDEX_DATE
							+ "", productService.getDate());
					jsonObject.put(
							CONSTANTS.PRODUCT_TAKE_OUT.COLUMN_INDEX_MACHINE_CODE
									+ "", productService.getMachineCode());
					jsonObject.put(
							CONSTANTS.PRODUCT_TAKE_OUT.COLUMN_INDEX_PRODUCT_CODE
									+ "", productService.getCodeProduct());
					jsonObject.put(
							CONSTANTS.PRODUCT_TAKE_OUT.COLUMN_INDEX_STAFF_CHECKER
									+ "", productService.getStaffChecker());
					jsonObject.put(
							CONSTANTS.PRODUCT_TAKE_OUT.COLUMN_INDEX_STAFF_SERVICE
									+ "", productService.getStaffService());

					jsonArrayTakeOut.put(jsonObject);
				}
			}

			JSONObject jsonObjectElementTakeOut = new JSONObject();
			jsonObjectElementTakeOut.put(JSON.KEY_TYPE + "",
					CLIENT_TRANSACTION.PRODUCT_TAKEOUT);
			jsonObjectElementTakeOut.put(JSON.KEY_VALUE + "",
					jsonArrayTakeOut.toString());
			jsonArraySend.put(jsonObjectElementTakeOut);

		} catch (JSONException e)
		{
			e.printStackTrace();
			return false;
		}

		/* Process box inventory */
		/* Create JSON */
		JSONArray jsonArrayBoxInventory = new JSONArray();
		try
		{
			for (BoxInventory boxInventory : boxInventories)
			{

				JSONObject jsonObject = new JSONObject();

				jsonObject.put(
						CONSTANTS.BOX_INVENTORY.COLUMN_INDEX_AMOUNT + "",
						boxInventory.getProductAmount());

				jsonObject.put(CONSTANTS.BOX_INVENTORY.COLUMN_INDEX_BOX_CODE
						+ "", boxInventory.getIdBox());

				jsonObject.put(
						CONSTANTS.BOX_INVENTORY.COLUMN_INDEX_MACHINE_CODE + "",
						boxInventory.getMachineCode());

				jsonObject.put(
						CONSTANTS.BOX_INVENTORY.COLUMN_INDEX_PRODUCT_CODE + "",
						boxInventory.getProductCode());

				jsonArrayBoxInventory.put(jsonObject);
			}
			JSONObject jsonObjectElementBoxInventory = new JSONObject();
			jsonObjectElementBoxInventory.put(JSON.KEY_TYPE + "",
					CLIENT_TRANSACTION.BOX_INVENTORY);
			jsonObjectElementBoxInventory.put(JSON.KEY_VALUE + "",
					jsonArrayBoxInventory.toString());
			jsonArraySend.put(jsonObjectElementBoxInventory);

		} catch (JSONException e)
		{
			e.printStackTrace();
			return false;
		}

		/* Process box information */
		/* Create JSON */

		JSONArray jsonArrayBox = new JSONArray();
		try
		{
			for (Box box : boxes)
			{

				JSONObject jsonObject = new JSONObject();

				// jsonObject.put(
				// CONSTANTS.BOX.COLUMN_INDEX_ACTIVE + "",
				// box.getActive());

				jsonObject.put(CONSTANTS.BOX.COLUMN_INDEX_ID + "", box.getId());

				// jsonObject.put(
				// CONSTANTS.BOX.COLUMN_INDEX_NAME + "",
				// box.getName());

				jsonObject.put(CONSTANTS.BOX.COLUMN_INDEX_PRODUCT_AMOUNT + "",
						box.getProductAmount());

				jsonObject.put(CONSTANTS.BOX.COLUMN_INDEX_PRODUCT_CODE + "",
						box.getProductCode());

				jsonObject.put(CONSTANTS.BOX.COLUMN_INDEX_PRODUCT_PRICE + "",
						box.getProductPrice());

				jsonArrayBox.put(jsonObject);
			}

			JSONObject jsonObjectElementBox = new JSONObject();
			jsonObjectElementBox.put(JSON.KEY_TYPE + "", CLIENT_TRANSACTION.BOX);
			jsonObjectElementBox.put(JSON.KEY_VALUE + "",
					jsonArrayBox.toString());
			jsonArraySend.put(jsonObjectElementBox);

		} catch (JSONException e)
		{
			e.printStackTrace();
			return false;
		}

		/* Send */
		try
		{
			jsonObjectSend.put(CONSTANTS.JSON.KEY_TYPE + "",
					CONSTANTS.CLIENT_TRANSACTION.UPDATE_DATA);

			jsonObjectSend.put(CONSTANTS.JSON.KEY_VALUE + "",
					jsonArraySend.toString());

		} catch (JSONException e)
		{
			e.printStackTrace();
			return false;
		}

		Utils.debug("Sending message = " + jsonObjectSend.toString());
		NetworkMina.send(jsonObjectSend.toString());

		return true;

	}

	//
	// public static String getHost()
	// {
	// return _host;
	// }

	public static void setHost(String _host)
	{
		NetworkMina._host = _host;
	}

	//
	// public static int getPort()
	// {
	// return _port;
	// }

	public static void setPort(int _port)
	{
		NetworkMina._port = _port;
	}

	public static GeneralActivity getOnNetworkHandleListener()
	{
		return onNetworkHandleListener;
	}

	public static void setOnNetworkHandleListener(
			GeneralActivity onNetworkHandleListener)
	{
		NetworkMina.onNetworkHandleListener = onNetworkHandleListener;
	}
}
